
/**********************************************************************************\
** 文件名称: chpwm.c
** 创建人员: YCG
** 创建日期: 2018-11-10
** 文档描述:
** 版本代号: V0.1
** 版本说明: 初始版本
\********************************************************************************/
#include "chpwm.h"
static  uint8_t PWMTxBuf[PWMBUFLENGH];
static  uint8_t PWMRxBuf[PWMBUFLENGH];
static  uint8_t OneBitNum;   //一个比特位的脉冲个数
static  uint32_t CountingTime = 0;
buf_struct PWMTx[1];
buf_struct PWMRx[1];
static volatile uint8_t  ReceFlag = PWM_RECE_FALLING, ReceState = PWM_START;              //接收电平状态，数据位接收状态
static volatile uint8_t  bitNum, byteNum,  receResult;          //接收的脉冲数，接收的位数，脉宽的平均值，接收结果保存
static volatile uint32_t DutyTime = 0, bitAverage=0,StartTime = 0;                      //脉宽，起始时间
void PwmInit(uint8_t bitnum) {
    BufInit(PWMTx, PWMTxBuf, PWMBUFLENGH);  //初始化发送缓存
    BufInit(PWMRx, PWMRxBuf, PWMBUFLENGH);  //初始化接收缓存
    OneBitNum = bitnum;                     //初始化一个比特位的脉冲个数
    TIM3_GPIO_Config();                     //初始化引脚
    TIM3_Mode_Config(PWM_PERIOD);           //初始化定时器模式
}

/*******************************************************************************
** 函数名称: PwmSendScan
** 功能描述: 放入定时器中断中，每次发完一个数据后会自动从缓存中读取一个数据进行发送
** 参数说明: None
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-11-19
********************************************************************************/
void PwmSendScan(void) {
    static uint8_t SendState = 0, SendChar;  //state用来保存状态，c用来保存需要发送的字符
    static uint8_t  SendBitNum;              //表示当前在发送第几位
    static uint16_t SendAllNum;              //表示总共已经发送了多少脉冲

    switch (SendState)
    {
    case PWM_START:                                  //起始状态
        if(BufUseSpace(PWMTx) > 0) {                 //如果发送缓存有数据
            TIM3->CCER |= 0x00000001; 			         //打开输出
            TIM_SetCompare1(TIM3, PWM_START_DUTY);   //设置起始信号
            SendChar = BufRead(PWMTx);               //从缓存中获取一个数据
            SendBitNum = 0;                          //清零位数
            SendAllNum = 0;                          //清零脉冲数
            SendState = PWM_DEAL;                    //切换到下一状态
        } else {
            TIM3->CCER &= ~0x00000001; 			         //关闭输出
        }
        break;

    case PWM_DEAL:                               //发送数据状态
        if(SendChar & 0x01) {                    //判断需要发送的数据位,最低位开始发送
            TIM_SetCompare1(TIM3, PWM_1_DUTY);;  //发送1
        } else {
            TIM_SetCompare1(TIM3, PWM_0_DUTY);;  //发送0
        }
        SendAllNum++;                            //发送脉冲计数加一
        if(SendAllNum % OneBitNum == 0) {            //如果已经发送完了一个比特位的脉冲
            SendChar >>= 1;                      //发送的字符右移一位
            ++SendBitNum ;
            if(SendBitNum >= 8) {
                SendState = PWM_END;              //切换到下一状态
            }
        }
        break;

    case PWM_END :
        SendState = PWM_START;                    //已经发送完一个数据，返回起始状态发送第一位
        break;

    default:
        SendState = PWM_START;                    //发送出错时返回起始状态
        break;
    }
}

/*******************************************************************************
** 函数名称: PWM_SendChar
** 功能描述: 发送一个字符
** 参数说明: dat: [输入] 发送的字符数据
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-11-26
********************************************************************************/
void PWM_SendChar(uint8_t dat) {
    while(BufUnuseSpace(PWMTx) == 0) {}            //如果缓存中实在没有空间了，只能等待了
    BufWrite(PWMTx, dat);                          //向缓存中写入一个数据
}

/*******************************************************************************
** 函数名称: PWM_SendString
** 功能描述: 发送字符串
** 参数说明: ch: [输入]  需要发送的字符串指针
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-11-26
********************************************************************************/
void PWM_SendString(char* ch){
	while(*ch!=0){
	PWM_SendChar(*ch);
		ch++;
	}
}
/*******************************************************************************
** 函数名称: Approximate
** 功能描述: 判断是否在给定范围以内
** 参数说明: value: [输入]  需要比较的值
**			     midpoint: [输入]    范围中心点
**			     range: [输入/出]    范围大小
** 返回说明: 1：在范围内  0：不在范围内
** 创建人员: YCG
** 创建日期: 2018-11-24
********************************************************************************/
uint8_t Approximate(uint32_t value, uint32_t midpoint, uint32_t range ) {
    if(value > midpoint - range && value < midpoint + range) {
        return 1;
    } else {
        return 0;
    }
}

/*******************************************************************************
** 函数名称: PWM_ReceDuty
** 功能描述: 计算接收到后的定时器周期
** 参数说明: : [输入]
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-11-24
********************************************************************************/
void PWM_RecePeriod(void) {
    CountingTime += PWM_PERIOD;        //定时器更新中断中计数，表明5000
}

/*******************************************************************************
** 函数名称: PWM_ReceDeal
** 功能描述: 接收处理
** 参数说明: : [输入/出]
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-11-24
********************************************************************************/
void PWM_ReceScan(void) {

    if(TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET) {                         //上升沿中断
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);                             //清除标志位
        if(ReceFlag == PWM_RECE_FALLING) {		                               //判断上一次是不是下降沿
            // PeriodTime = TIM_GetCapture3(TIM3) + CountingTime - StartTime;  //计算出周期的计数值，不需要的话就不要
            StartTime = TIM_GetCapture3(TIM3);                               //保存开始的时间
            ReceFlag = PWM_RECE_RISING;                                       //更新接收状态
            CountingTime = 0; 	                                             //周期重新计数
        }
    }

    if(TIM_GetITStatus(TIM3, TIM_IT_CC4) != RESET) {                      //下降沿中断
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);                          //清除标志位
        if(ReceFlag == PWM_RECE_RISING) {                                 //判断上一次是不是上升沿
            DutyTime = TIM_GetCapture4(TIM3) + CountingTime - StartTime;  //计算出周期的计数值
            ReceFlag = PWM_RECE_FALLING;
            switch (ReceState)                                            //接收数据处理
            {
            case PWM_START:
                if(Approximate(DutyTime, PWM_START_DUTY, PWM_RANGE)) {    //假如检测到起始位
                    bitNum = 0;                                           //初始化本次接收的变量
                    byteNum = 0;
                    bitAverage = 0;
                    receResult = 0;
                    ReceState = PWM_DEAL;                                 //进入下一个状态
                }
                break;
								
            case PWM_DEAL:
                bitNum++;                                 //接收到的脉冲数计数
                if(bitNum <= OneBitNum) {                 //少于一个位的脉冲数
                    bitAverage += DutyTime;               //将脉冲时间进行累加
                }
                if(bitNum == OneBitNum) {                 //接收到了给定数量的脉冲
									  bitNum=0;
                    bitAverage /= OneBitNum;              //取平均值
                    byteNum++;                            //接收到的位数加一
									  receResult >>= 1;                     //结果右移一位，留出空间来保留准备接收的数据
                    if(Approximate(DutyTime, PWM_0_DUTY, PWM_RANGE)) {           //读取到 0，因为本来就是0 ，不做任何处理
                   //      receResult |= 0x80;
                    } else if(Approximate(DutyTime, PWM_1_DUTY, PWM_RANGE)) {   //读取到 1，将其存入结果中
                        receResult |= 0x80;
                    } else {                                                     //假如没有满足条件的话，就是出错了，先不进行处理
                        //预留的错误处理程序
                    }
                    if(byteNum >= 8) { //八次就接收完一字节的数据了
                        BufWrite(PWMRx, receResult);  //将接收到的数据写入缓存
                        ReceState = PWM_START;        //恢复起始状态，等待下一个数据接收接收
                    }
										bitAverage=0;										
                }
                break;
								
            case PWM_END:
                break;
            }

        }
    }


}

/********************************End of File************************************/
